﻿using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Graphics;
using Ninject;
using SomeRandomGame.Guns;
using SomeRandomGame.Interfaces;
using SomeRandomGame.Particles;
using SomeRandomGame.Particles.Engines;
using SomeRandomGame.Utility;

namespace SomeRandomGame.Ships
{
    public class StandardPlayerShip :IShip
    {
        private IGameEntity _shipObject;
        private ShipMotorParticleEngine _shipMotorParticleEngine;
        private Vector2 _currentForceOnShip = new Vector2( 0, 0 );
        private IGun _shipLaserGun;
        private const float _mass = 1.0f;

        public Vector2 Position
        {
            get { return _shipObject.Position; }
            set { _shipObject.Position = value;
                _shipMotorParticleEngine.EmitterLocation = GetMotorPosition(value);
                _shipLaserGun.EmitterLocation = GetLaserPosition(value);
            }
        }

        private Vector2 GetLaserPosition(Vector2 shipPosition)
        {
            return new Vector2(shipPosition.X + _shipObject.Width / 2 + 10, shipPosition.Y);
        }

        private Vector2 GetMotorPosition(Vector2 shipPosition)
        {
            return new Vector2(shipPosition.X - _shipObject.Width/2, shipPosition.Y);
        }

        public int Width { get { return _shipObject.Width; } }
        public int Height { get { return _shipObject.Height; } }
        public IGun Gun { get { return _shipLaserGun; } }
        public float Speed { get { return Constants.Controls.STANDARD_MOVEMENT_SPEED; } }
        public bool Active { get { return true; } }

        // NOTE: Inertia doesnt really work. This code is just some playing around
        public void Move( PlayerIndex playerIndex, IGameManager gameManager, IInputManager inputManager )
        {
            Vector2 shipSpeed = inputManager.GetInputVector( playerIndex, Speed );

            if( shipSpeed.Equals( Vector2.Zero ) )
            {
                _currentForceOnShip = Vector2.Zero;
                return;
            }

            _currentForceOnShip += shipSpeed;
            Vector2 airResistenceForce = new Vector2( shipSpeed.X * shipSpeed.X * Constants.Physics.AIR_RESISTENCE, shipSpeed.Y * shipSpeed.Y * Constants.Physics.AIR_RESISTENCE );

            if( shipSpeed.X < 0.0f )
            {
                _currentForceOnShip.X += airResistenceForce.X;
            }
            else
            {
                _currentForceOnShip.X -= airResistenceForce.X;
            }

            if( shipSpeed.Y < 0.0f )
            {
                _currentForceOnShip.Y += airResistenceForce.Y;
            }
            else
            {
                _currentForceOnShip.Y -= airResistenceForce.Y;
            }

            float accelerationX = _currentForceOnShip.X / _mass;
            float accelerationY = _currentForceOnShip.Y / _mass;

            shipSpeed.X += accelerationX * (float)gameManager.GameTime.ElapsedGameTime.TotalSeconds;
            shipSpeed.Y += accelerationY * (float)gameManager.GameTime.ElapsedGameTime.TotalSeconds;

            Vector2 shipPosition = _shipObject.Position;
            shipPosition.X += shipSpeed.X * (float)gameManager.GameTime.ElapsedGameTime.TotalSeconds;
            shipPosition.Y += shipSpeed.Y * (float)gameManager.GameTime.ElapsedGameTime.TotalSeconds;

            shipPosition.X = MathHelper.Clamp( shipPosition.X, _shipObject.Width / 2, gameManager.Game.GraphicsDevice.Viewport.Width - _shipObject.Width / 2 );
            shipPosition.Y = MathHelper.Clamp( shipPosition.Y, _shipObject.Height / 2, gameManager.Game.GraphicsDevice.Viewport.Height - _shipObject.Height / 2 );

            _shipObject.Position = shipPosition;
            _shipMotorParticleEngine.EmitterLocation = GetMotorPosition(shipPosition);
            _shipLaserGun.EmitterLocation = GetLaserPosition(shipPosition);
        }

        public void Initialize( IGameManager gameManager )
        {
            _shipObject = (IGameEntity)gameManager.ServiceLocator.Get<IContentFactory>().Get( Constants.Content.Animations.STANDARD_PLAYER_SHIP );
            Texture2D shipMotorParticleTexture = gameManager.ServiceLocator.Get<IContentFactory>().GetTexture(Constants.Content.Particles.SHIP_MOTOR_PARTICLE);
            _shipMotorParticleEngine = new ShipMotorParticleEngine(shipMotorParticleTexture,GetMotorPosition(_shipObject.Position));
            Texture2D laserParticleTexture = gameManager.ServiceLocator.Get<IContentFactory>().GetTexture(Constants.Content.Particles.LASER_PARTICLE);
            SoundEffect laserSound = gameManager.ServiceLocator.Get<IContentFactory>().LaserSound;
            Effect laserEffect = gameManager.Game.Content.Load<Effect>("Effects/Blur");
            _shipLaserGun = new LaserGun(laserParticleTexture, GetLaserPosition(_shipObject.Position), 10,laserSound, laserEffect);
        }

        public void Update(IGameManager gameManager)
        {
            _shipObject.Update(gameManager);
            _shipLaserGun.Update(gameManager);
            _shipMotorParticleEngine.Update(gameManager);
        }

        public void Draw( SpriteBatch spriteBatch, IGameManager gameManager, GameTime gameTime )
        {
            _shipObject.Draw( spriteBatch, gameManager, gameTime );
            _shipMotorParticleEngine.Draw(spriteBatch, gameManager, gameTime);
            _shipLaserGun.Draw(spriteBatch, gameManager, gameTime);
        }
    }
}
